package com.lixin.juc.threadpool;

import java.util.concurrent.*;

public class MainApplication {

    public static void main(String[] args) {
        //testExecutors();
        testThreadPool();
    }

    public static void testThreadPool() {
        /*
        拒绝策略
        ThreadPoolExecutor.AbortPolicy 抛出异常
        ThreadPoolExecutor.CallerRunsPolicy 回到原来的线程中去执行，这里会回到主线程(mainThread)中去执行，不会抛出异常
        ThreadPoolExecutor.DiscardPolicy 直接丢弃任务，不会抛出异常
        ThreadPoolExecutor.DiscardOldestPolicy() 尝试丢弃等待队列中最老的任务，并将新任务加入等待队列中（在线程较少的情况下与DiscardPolicy效果基本一样）
         */
        ThreadPoolExecutor threadPool = new ThreadPoolExecutor(
                2, // 核心线程数
                5, // 最大线程数
                2, // 等待超时时间
                TimeUnit.SECONDS, // 超时时间单位
                new ArrayBlockingQueue<>(3), // 等待队列
                Executors.defaultThreadFactory(), // 线程工厂（用来创建线程）
                new ThreadPoolExecutor.DiscardOldestPolicy() // 拒绝策略，AbortPolicy是抛出异常
        );
        /*
        要执行的任务数量 <= 核心线程数 + 等待队列大小，不会创建新线程
        要执行的任务数量 > 核心线程数 + 等待队列大小，会创建新线程来一起处理任务，但线程总数不会超过最大线程数
        如果超过了最大线程数，则会抛出java.util.concurrent.RejectedExecutionException异常
        所以能承受的最大任务数量 = 最大线程数 + 等待队列大小
         */
        try {
            for (int i = 1; i <= 20; i++) {
                threadPool.execute(() -> {
                    System.out.println(Thread.currentThread().getName() + "正在执行任务");
                });
            }
            System.out.println("我这里开始了！");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            threadPool.shutdown();
        }
    }

    // 工作中不要用
    public static void testExecutors() {
        // 只允许一个线程运行
        //ExecutorService threadPool = Executors.newSingleThreadExecutor();

        // 固定5个线程运行
        //ExecutorService threadPool = Executors.newFixedThreadPool(5);

        // 根据要执行的任务来动态创建线程，线程数不固定
        ExecutorService threadPool = Executors.newCachedThreadPool();

        try {
            for (int i = 1; i <= 40; i++) {
                threadPool.execute(() -> {
                    System.out.println(Thread.currentThread().getName() + "正在执行任务");
                });
            }
            System.out.println("我这里开始了！");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            threadPool.shutdown();
        }
    }

}
